package com.jade.journal.desc.field;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import com.jade.framework.base.lang.ReflectUtils;
import com.jade.framework.base.lang.ServiceLocator;

/**
 * 日志字段类型
 *
 * @author fengyun
 * @version Jan 10, 2003 12:46:19 PM
 */
public abstract class FieldType
{
    /** 类型名称 */
    private String name;

    /**
     * 构造
     *
     * @param name
     */
    public FieldType(String name)
    {
        this.name = name;
    }

    /**
     * 返回类型名称
     *
     * @return 类型名称
     */
    public final String getName()
    {
        return name;
    }

    /**
     * 将指定的数据转换成对象
     *
     * @param data 字节数组
     * @return 返回对象
     */
    public Object getObject(byte[] data)
    {
        return getObject(data, 0, data.length);
    }

    /**
     * 将指定的数据转换成对象
     *
     * @param data 字节数组
     * @param off  起始位置
     * @param len  长度
     * @return 返回对象
     */
    public abstract Object getObject(byte[] data, int off, int len);

    /**
     * 将指定的数据转换成对象
     *
     * @param data 字节数组
     * @return 返回对象
     */
    public Object getObject(char[] data)
    {
        return getObject(data, 0, data.length);
    }

    /**
     * 将指定的数据转换成对象
     *
     * @param data 字节数组
     * @param off  起始位置
     * @param len  长度
     * @return 返回对象
     */
    public abstract Object getObject(char[] data, int off, int len);

    /**
     * 指定数据转换成字符串
     *
     * @param data 字节数组
     * @return 返回字符串
     */
    public String getString(byte[] data)
    {
        return getString(data, 0, data.length);
    }

    /**
     * 指定数据转换成字符串
     *
     * @param data 字节数组
     * @param enc  字符集
     * @return 返回字符串
     */
    public String getString(byte[] data, String enc)
    {
        return getString(data, 0, data.length, enc);
    }

    /**
     * 指定数据转换成字符串
     *
     * @param data 字节数组
     * @param off  起始位置
     * @param len  长度
     * @return 返回字符串
     */
    public String getString(byte[] data, int off, int len)
    {
        return getString(data, off, len, Charset.defaultCharset().name());
    }

    /**
     * 指定数据转换成字符串
     *
     * @param data 字节数组
     * @return 返回字符串
     */
    public String getString(char[] data)
    {
        return new String(data);
    }

    /**
     * 指定数据转换成字符串
     *
     * @param data 字节数组
     * @param off  起始位置
     * @param len  长度
     * @return 返回字符串
     */
    public String getString(char[] data, int off, int len)
    {
        return new String(data, off, len);
    }

    /**
     * 指定数据转换成字符串
     *
     * @param data 字节数组
     * @param off  起始位置
     * @param len  长度
     * @return 返回字符串
     */
    public abstract String getString(byte[] data, int off, int len, String enc);

    /**
     * 按照默认的字符集返回字符串
     *
     * @param data 字节数组
     * @param off  起始位置
     * @param len  长度
     * @return 返回字符串
     */
    protected String getDefaultString(byte[] data, int off, int len)
    {
        return new String(data, off, len);
    }

    /**
     * 按照默认的字符集返回字符串
     *
     * @param data 字节数组
     * @param off  起始位置
     * @param len  长度
     * @return 返回字符串
     */
    protected String getDefaultString(char[] data, int off, int len)
    {
        return new String(data, off, len);
    }

    /**
     * 按照默认的字符集返回字符串
     *
     * @param data 字节数组
     * @param off  起始位置
     * @param len  长度
     * @return 返回字符串
     */
    protected String getDefaultString(byte[] data, int off, int len, String enc)
    {
        try {
            return new String(data, off, len, enc);
        }
        catch (UnsupportedEncodingException ue) {
            return getDefaultString(data, off, len);
        }
    }

    /**
     * 返回字符串信息
     *
     * @return 字符串信息
     */
    public String toString()
    {
        return getName();
    }

    //类型汇总
    private static Map<String, FieldType> name2Type = new HashMap<String, FieldType>(19);
    private static Properties props = ServiceLocator.getImplementProperties(FieldType.class, false);
    private static FieldType defType = getType("String");

    /**
     * 根据名称返回类型，如果找不到该类型，返回StringType
     *
     * @param name 类型名称s
     * @return 类型
     */
    public static FieldType getType(String name)
    {
        FieldType type = name2Type.get(name);
        if (type == null) {
            synchronized (FieldType.class) {
                type = name2Type.get(name);

                String n = name.toLowerCase();
                String className = props.getProperty(n);
                if (className != null) {
                    type = (FieldType)ReflectUtils.newSingleton(className);
                    if (type != null) {
                        name2Type.put(n, type);
                    }
                }
            }
        }
        return type == null ? defType : type;
    }

    /**
     * 增加字段类型
     *
     * @param type 字段类型
     */
    public static void addType(FieldType type)
    {
        name2Type.put(type.getName(), type);
    }

    /**
     * 返回默认的字段类型
     *
     * @return 默认字段类型
     */
    public static FieldType getDefault()
    {
        return defType;
    }
}
